package com.example.lambda

import org.junit.Test


/**
 * 内置函数测试
 *
 * @author zhouronghua
 * @time 2022/3/26 3:10 下午
 */
class HighInnelTest {

    @Test
    fun testMapHigh() {
        listOf("afdsaf", "BBB", "CCC").zip(listOf(1, 3, 6)).toMap()
            .map {
                println("Entry key: ${it.key}, value: ${it.value}")
            }
        // 测试高阶函数调用
        println(study01()("明明", 25))
        // 测试更复杂的高阶函数study02()
        study02()({ num1, num2 -> "两数 $num1 $num2 相加的结果是${num1 + num2}" }, "小豆子")
        // 测试泛型函数
        println("测试泛型高阶函数")
        study05<String, Int, Int, Boolean>()("丽丽", 25, {
            it.length
        }) {
            it > 20
        }
        // 测试函数的尹红
        println(study06()("小可爱", 18, {
            println("Lambda将字符串转换为整形")
            it.length
        }))
        // 测试自己写的内置函数
        val result = "AAAA".myApply {
            println("当前输入内容是 $this")
        }
        println("myApply转换后结果 $result")
    }

    /**
     * study06()函数指向一个fun函数
     */
    fun study06() = fun(str: String, num: Int, lambda: (String) -> Int): Int {
        true
        "haha"
        println("将输入参数 $str $num")
        // fun函数需要显式声明返回值类型为Int，即lambda(str)的返回值类型，采用return标记
        return num + lambda(str)
    }

    /**
     * 采用泛型版本改造study04()
     */
    fun <T1, T2, R1, R2> study05() = { str: T1, num: T2, lambda1: (T1) -> R1, lambda2: (T2) -> R2 ->
        println("调用了lambda1的结果是 ${lambda1(str)}  ${if (lambda1(str) is Int) "变化后的类型是整形" else "你变换后的不是整形"}")
        println("调用了lambda2 的结果是 ${lambda2(num)}")
    }

    /**
     * study04()是一个函数，
     * 输入类型：(String, Int, (String)->Unit, Int->Unit)
     * 返回值Unit
     */
    fun study04() = { str: String, num: Int, lambda1: (String) -> Unit, lambda2: (Int) -> Unit ->
        lambda1(str)
        // lambda2的返回值是Unit, lambda2(num)执行后的类型为Unit,即study04()的返回类型是Unit
        lambda2(num)
    }

    /**
     * study03()是一个函数，返回类型：(String, Int)->Boolean
     */
    fun study03() = { str: String, num: Int ->
        true
    }

    /**
     * study02()是个高阶函数，输入参数是一个高阶函数，返回值是Unit
     * 函数名是study02()，这是一个整体
     *     高阶函数类型((Int, Int) -> String, String)->Unit
     * 返回值含有两个参数：第一个参数是函数 lambda: (Int, Int) -> String，对应函数类型(Int, Int) -> String
     *                                          Lambda函数的实现需要用户定义
     *                                     第二个参数名是：studyInfo，对应类型是String
     */
    fun study02() = { lambda: (Int, Int) -> String, studyInfo: String ->
        false
        "那没人"
        // 此处带入用户实现lambda(10, 10) = { num1, num2 -> "两数 $num1 $num2 相加的结果是${num1 + num2}" }
        // 执行结果返回给变量lambdaAction
        val lambdaAction = lambda(10, 10)
        // 字符串模板输出结果
        println("最后我组装的结果是 $lambdaAction + $studyInfo ")
    }

    /**
     * 函数的返回类型是(String, Int) -> String
     */
    fun study01() = { name: String, age: Int ->
        true
        name
        age
        "我的姓名是$name 年龄是 $age"
    }

}

/**
 * 全局扩展函数
 * T.myApply： 对任意类型T扩展myApply函数
 * T.myApply函数的输入类型是Lambda函数：()->Unit，输入类型是T(与输入参数相同)
 * lambda: T.() -> Unit：Lambda是一个T的匿名扩展函数，Lambda实现体内部持有对象的this
 */
fun <T> T.myApply(lambda: T.() -> Unit): T {
    lambda()
    return this
}